package com.ego.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ego.auth.entity.UserInfo;
import com.ego.exception.EgoException;
import com.ego.exception.ExceptionEnum;
import com.ego.pojo.utils.CodecUtils;
import com.ego.pojo.utils.NumberUtils;
import com.ego.user.interceptor.LoginInterceptor;
import com.ego.user.mapper.UserMapper;
import com.ego.user.pojo.User;
import com.ego.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Ares
 * @date 2020-12-7
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    private final static String SMS_KEY_PRE = "ego:verify";

    @Resource
    private AmqpTemplate amqpTemplate;

    @Resource
    private UserMapper userMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Boolean check(String data, Integer type) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        switch (type) {
            case 1:
                wrapper.eq("username", data);
                break;
            case 2:
                wrapper.eq("phone", data);
        }
        Integer integer = userMapper.selectCount(wrapper);
        return integer > 0 ? false : true;
    }

    /**
     * 注册用户
     *
     * @param user 用户实体
     * @param code 验证码
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(User user, String code) {
        //1.判断验证码

        String redisCode = stringRedisTemplate.opsForValue().get(SMS_KEY_PRE + user.getPhone());
        if (StringUtils.isBlank(code) || !code.equals(redisCode)) {
            log.debug("验证码不匹配");
            throw new EgoException(ExceptionEnum.VERIFY_CODE_NOT_MATCHING);
        }
        //2.验证表单数据(数据格式&数据是否存在)
        if (!this.check(user.getUsername(), 1)) {
            log.debug("用户名已存在");
            throw new EgoException(ExceptionEnum.USER_EXIST);
        }
        if (!this.check(user.getPhone(), 2)) {
            log.debug("手机已存在");
            throw new EgoException(ExceptionEnum.PHONE_EXIST);
        }
        try {
            //3.保存到mysql数据库
            user.setCreated(new Date());
            //将明文密码加密存储
            String encodePass = CodecUtils.passwordBcryptEncode(user.getUsername(), user.getPassword());
            user.setPassword(encodePass);
            userMapper.insert(user);
            //4.删除验证码
            stringRedisTemplate.delete(SMS_KEY_PRE + user.getPhone());
        } catch (Exception e) {
            log.error("保存用户失败", e);
            throw new EgoException(ExceptionEnum.USER_SAVE_ERROR);
        }
    }

    @Override
    public void sendSms(String phone) {
        //1.生成验证码
        String code = NumberUtils.generateCode(6);
        try
        {
            //2.将验证码存入redis（5分钟）
            stringRedisTemplate.opsForValue().set(SMS_KEY_PRE+phone, code,5, TimeUnit.MINUTES);
            //3.发消息到rabbitmq
            Map<String, String> map = new HashMap<>(2);
            map.put("phone",phone);
            map.put("code",code);
            amqpTemplate.convertAndSend("ego.sms.exchange","sms.send",map);
        }catch (Exception e){
            log.error("发送短信失败。phone：{}， code：{}", phone, code);
            throw new EgoException(ExceptionEnum.SEND_MSG_EXCEPTION);
        }
    }

    @Override
    public User queryUser(String username, String password) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
        if(user==null){
            return null;
        }
        //判断密码是否正确
        if(!CodecUtils.passwordConfirm(username+password,user.getPassword())){
            return null;
        }
        return user;
    }

    @Override
    @Transactional
    public String updatePassword(String oldPassword, String password) {

        UserInfo userInfo = LoginInterceptor.getLoginUser();

        User byUsername = userMapper.selectOne(new QueryWrapper<User>().eq("username", userInfo.getUsername()));

        //判断密码是否正确
        if(!CodecUtils.passwordConfirm(userInfo.getUsername()+oldPassword,byUsername.getPassword())){
            return "当前密码不正确";
        }
        //密码加密
        byUsername.setPassword(CodecUtils.passwordBcryptEncode(userInfo.getUsername(),password));

        int i = userMapper.updateById(byUsername);
        if(i>0){
            return "密码已修改";
        }
        return null;
    }

    @Override
    @Transactional
    public String findPhone() {
        UserInfo userInfo = LoginInterceptor.getLoginUser();
        User byUsername = userMapper.selectOne(new QueryWrapper<User>().eq("username", userInfo.getUsername()));
        return byUsername.getPhone();
    }

    @Override
    public Boolean confirm(String code,String phone) {

        //判断验证码是否正确
        String redisCode = stringRedisTemplate.opsForValue().get(SMS_KEY_PRE+phone);
        if(redisCode == null){
            return false;
        }
        if(redisCode.equals(code)){
            return true;
        }
        return false;
    }

    @Override
    @Transactional
    public Boolean updatePhone(String code, String phone) {
        //判断验证码是否正确
        String redisCode = stringRedisTemplate.opsForValue().get(SMS_KEY_PRE+phone);
        if(redisCode == null || !redisCode.equals(code)){
            return false;
        }
        UserInfo userInfo = LoginInterceptor.getLoginUser();
        User byUsername = userMapper.selectOne(new QueryWrapper<User>().eq("username", userInfo.getUsername()));

        byUsername.setPhone(phone);

        int i = userMapper.updateById(byUsername);
        if(i>0){
            return true;
        }
        return false;

    }
}
